﻿using CQRSFramework.Commands;
using CQRSFramework.Domains;
using CQRSFramework.Infrustructures;
using System;
using System.Collections.Generic;

namespace CQRSFramework.Events.Impl
{
    public class EventService : IEventService
    {
        private IEventStore _eventStore;
        private ITypeNameProvider _typeNameProvider;
        private IDomainEventPublisher _domainEventPublisher;
        public EventService(IEventStore eventStore, ITypeNameProvider typeNameProvider, IDomainEventPublisher domainEventPublisher)
        {
            _eventStore = eventStore;
            _typeNameProvider = typeNameProvider;
            _domainEventPublisher = domainEventPublisher;
        }
        public void CommitDomainEvents(ICommand command, IAggregateRoot aggregateRoot, IEnumerable<IDomainEvent> domainEvents)
        {
            //可能由于断电或者网络等原因，导致事件已经持久化到事件库了，未成功ack。
            //先判断是否成功持久化到事件库，如果成功持久化，则发布该事件
            var result = _eventStore.Find(aggregateRoot.UniqueAggregateRootId, command.Id);
            if (result == null)
            {
                //如果eventstore保存后，突然断电了,会造成系统不一致性。
                _eventStore.Append(new DomainEventStream
                {
                    CommandId = command.Id,
                    AggregateRootId = aggregateRoot.UniqueAggregateRootId,
                    AggregateRootTypeName = _typeNameProvider.GetTypeName(aggregateRoot.GetType()),
                    Version = aggregateRoot.Version,
                    DomainEvents = domainEvents,
                    TimeStamp = DateTime.Now,
                });
            }
            else
            {
                PublishDomainEvents(domainEvents);
            }
        }

        public void PublishDomainEvents(IEnumerable<IDomainEvent> domainEvents)
        {
            _domainEventPublisher.Publish(domainEvents);
        }
    }
}
